﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using FIFP.Common;
using FIFP.DashBoard.Helper;
using FIFP.DashBoard.Model;
using System.Collections.Generic;
using Telerik.Windows.Controls;
using System.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel;
using FIFP.DashBoard.Views;
using FIFP.DashBoard.Converters;

namespace FIFP.DashBoard.ViewModel
{
    public class OverlapVM_New : ViewModelCore
    {
        #region Variables
        public event EventHandler<CustomEventArgs<AppointmentGroup>> OnAppointmentDataCompleted;
        int overlapId = 0;
        private bool isApplySimopsButtonEnabled = false;
        private bool isCancelSimopsButtonEnabled = false;
        #endregion

        #region Properties
        private List<FIFPAppointment> overlapOriginalPlans = new List<FIFPAppointment>();
        public List<FIFPAppointment> OverlapOriginalPlans
        {
            get { return overlapOriginalPlans; }
            set { SetPropertyValue(() => OverlapOriginalPlans, value, val => overlapOriginalPlans = val); }
        }

        private ObservableCollection<OverlapGroup> overlapLocations = new ObservableCollection<OverlapGroup>();
        public ObservableCollection<OverlapGroup> OverlapLocations
        {
            get { return overlapLocations; }
            set { SetPropertyValue(() => OverlapLocations, value, val => overlapLocations = val); }
        }

        private OverlapGroup selectedOverlapLocation;
        public OverlapGroup SelectedOverlapLocation
        {
            get { return selectedOverlapLocation; }
            set { SetPropertyValue(() => SelectedOverlapLocation, value, val => selectedOverlapLocation = val); }
        }

        private Dictionary<int, FIFPAppointment> originalPlansDictionary = new Dictionary<int, FIFPAppointment>();
        public Dictionary<int, FIFPAppointment> OriginalPlansDictionary
        {
            get { return originalPlansDictionary; }
            set { SetPropertyValue(() => OriginalPlansDictionary, value, val => originalPlansDictionary = val); }
        }

        private ObservableCollection<FIFPAppointment> overlappedActivities = new ObservableCollection<FIFPAppointment>();
        public ObservableCollection<FIFPAppointment> OverlappedActivities
        {
            get { return overlappedActivities; }
            set { SetPropertyValue(() => OverlappedActivities, value, val => overlappedActivities = val); }
        }

        private ObservableCollection<FIFPAppointment> selectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>();
        public ObservableCollection<FIFPAppointment> SelectedUnitOverlappedActivities
        {
            get { return selectedUnitOverlappedActivities; }
            set { SetPropertyValue(() => SelectedUnitOverlappedActivities, value, val => selectedUnitOverlappedActivities = val); }
        }

        private ObservableCollection<FIFPAppointment> modifiedActivities = new ObservableCollection<FIFPAppointment>();
        public ObservableCollection<FIFPAppointment> ModifiedActivities
        {
            get { return modifiedActivities; }
            set { SetPropertyValue(() => ModifiedActivities, value, val => modifiedActivities = val); }
        }

        private List<FIFPAppointment> selectedAppointments = new List<FIFPAppointment>();
        public List<FIFPAppointment> SelectedAppointments
        {
            get { return selectedAppointments; }
            set { SetPropertyValue(() => SelectedAppointments, value, val => selectedAppointments = val); }
        }

        private List<FIFPAppointment> selectedLocationOverlapList = new List<FIFPAppointment>();
        public List<FIFPAppointment> SelectedLocationOverlapList
        {
            get { return selectedLocationOverlapList; }
            set { SetPropertyValue(() => SelectedLocationOverlapList, value, val => selectedLocationOverlapList = val); }
        }

        private List<Unit> unitList = new List<Unit>();
        public List<Unit> UnitList
        {
            get { return unitList; }
            set { SetPropertyValue(() => UnitList, value, val => unitList = val); }
        }

        public bool IsApplySimopsButtonEnabled
        {
            get { return isApplySimopsButtonEnabled; }
            set { SetPropertyValue(() => IsApplySimopsButtonEnabled, value, val => isApplySimopsButtonEnabled = val); }
        }

        public bool IsCancelSimopsButtonEnabled
        {
            get { return isCancelSimopsButtonEnabled; }
            set { SetPropertyValue(() => IsCancelSimopsButtonEnabled, value, val => isCancelSimopsButtonEnabled = val); }
        }
        private int selectedOverlapId;
        public int SelectedOverlapId
        {
            get { return selectedOverlapId; }
            set { SetPropertyValue(() => SelectedOverlapId, value, val => selectedOverlapId = val); }
        }

        private int selectedCancelSIMOPSOverlapId;
        public int SelectedCancelSIMOPSOverlapId
        {
            get { return selectedCancelSIMOPSOverlapId; }
            set { SetPropertyValue(() => SelectedCancelSIMOPSOverlapId, value, val => selectedCancelSIMOPSOverlapId = val); }
        }
        private bool isCheckOverlapButtonEnabled = true;
        public bool IsCheckOverlapButtonEnabled
        {
            get { return isCheckOverlapButtonEnabled; }
            set { SetPropertyValue(() => IsCheckOverlapButtonEnabled, value, val => isCheckOverlapButtonEnabled = val); }
        }
        private Unit towerUnit;
        public Unit TowerUnit
        {
            get { return towerUnit; }
            set { SetPropertyValue(() => TowerUnit, value, val => towerUnit = val); }
        }

        private DataGrid locationGrid;
        public DataGrid LocationGrid
        {
            get { return locationGrid; }
            set { SetPropertyValue(() => LocationGrid, value, val => locationGrid = val); }
        }
        

        #endregion

        #region Commands
        private ICommand _OverlapLocationSelectionChanged;
        public ICommand OverlapLocationSelectionChanged
        {
            get
            {
                return _OverlapLocationSelectionChanged ??
                        (_OverlapLocationSelectionChanged = new RelayCommand<DataGrid>(OverlapLocationGridSelectionChange));
            }
        }

        private ICommand _OverlapLocationGridLoadingRowCommand;
        public ICommand OverlapLocationGridLoadingRowCommand
        {
            get
            {
                return _OverlapLocationGridLoadingRowCommand ??
                        (_OverlapLocationGridLoadingRowCommand = new RelayCommand<object>(OverlapLocationGridRowLoad));
            }
        }

        private ICommand _OverlapCheckCommand;
        public ICommand OverlapCheckCommand
        {
            get
            {
                return _OverlapCheckCommand ??
                        (_OverlapCheckCommand = new RelayCommand<Button>(CheckOverlapForSelectedLocation));
            }
        }

        private ICommand _ApplySimopsCommand;
        public ICommand ApplySimopsCommand
        {
            get
            {
                return _ApplySimopsCommand ??
                        (_ApplySimopsCommand = new RelayCommand<Button>(ApplySimopsClicked));
            }
        }

        private ICommand _CancelSimopsCommand;
        public ICommand CancelSimopsCommand
        {
            get
            {
                return _CancelSimopsCommand ??
                        (_CancelSimopsCommand = new RelayCommand<Button>(CancelSimopsClicked));
            }
        }

        private ICommand _OverlapActivityCheckedCommand;
        public ICommand OverlapActivityCheckedCommand
        {
            get
            {
                return _OverlapActivityCheckedCommand ??
                        (_OverlapActivityCheckedCommand = new RelayCommand<RadioButton>(IsApplicableForApplySIMOPS));
            }
        }
        private ICommand _OverlapModifiedActivityCheckedCommand;
        public ICommand OverlapModifiedActivityCheckedCommand
        {
            get
            {
                return _OverlapModifiedActivityCheckedCommand ??
                        (_OverlapModifiedActivityCheckedCommand = new RelayCommand<RadioButton>(IsApplicableForCancelSIMOPS));
            }
        }


        #endregion

        #region Constructor
        public OverlapVM_New()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                ServiceLocator.Get<MainPageVM>().OnOverlapClick += new EventHandler(OverlapVM_OnOverlapClick);
            }
        }
        #endregion

        #region Reset
        public void Reset()
        {
            overlapId = 0;
            OverlappedActivities = new ObservableCollection<FIFPAppointment>();//For retaining purposes, comment outed.
            ModifiedActivities = new ObservableCollection<FIFPAppointment>();
            SelectedAppointments = new List<FIFPAppointment>();
            OverlapLocations = new ObservableCollection<OverlapGroup>();
        }
        #endregion

        #region Methods
        void OverlapVM_OnOverlapClick(object sender, EventArgs e)
        {
            //if (OverlapLocations != null && OverlapLocations.Count == 0)
            {
                overlapId = 0;
                ServiceLocator.Get<AppointmentVM>().RadScheduleViewDragDropBehavior = new OverlapScheduleDragDropBehavior();
                OverlapOriginalPlans = ServiceLocator.Get<ImportVM>().ImportPlans;
                OverlapOriginalPlans.ForEach(s => { s.ActivityLevel = 1; });//Undo only page level
                UnitList = ServiceLocator.Get<ImportVM>().UnitList;
                LoadOriginalPlansIntoDictionary(OverlapOriginalPlans);
                CheckOverlap();

                foreach (FIFPAppointment appointment in OverlapOriginalPlans)
                {
                    if (appointment.IsAppliedSimops)
                        appointment.IsOverlapped = true;
                }
            }
            if (SelectedAppointments != null && SelectedAppointments.Count > 0)//for retaining previous state
            {               
                LoadOverlapPlans((from item in SelectedAppointments orderby item.nIndex ascending select item).ToList<FIFPAppointment>());
            }
        }

        private void LoadOriginalPlansIntoDictionary(List<FIFPAppointment> planList)
        {
            OriginalPlansDictionary.Clear();
            foreach (FIFPAppointment appointment in planList)
            {
                OriginalPlansDictionary.Add(appointment.PlanID, appointment);
                appointment.IsOverlapped = false;
            }
        }

        private void CheckOverlap()
        {
            List<string> unitTypes = (from item in OverlapOriginalPlans
                                      where item.nIndex > 0 && item.UnitType != FIFPConstants.UNITTYPE_STRING
                                      orderby item.nIndex ascending
                                      select item.UnitType).Distinct().ToList<string>();
            foreach (string unitType in unitTypes)
            {

                List<FIFPAppointment> plansWithUnitType = (from item in OverlapOriginalPlans
                                                           where item.UnitType == unitType
                                                           orderby item.nIndex ascending
                                                           select item).ToList<FIFPAppointment>();
                List<string> unitsWithTheSameUnitTypeList = (from item in plansWithUnitType
                                                             select item.UnitName).Distinct().ToList<string>();

                foreach (string unitName in unitsWithTheSameUnitTypeList)
                {
                    List<FIFPAppointment> plans = (from item in plansWithUnitType
                                                   where item.UnitName == unitName
                                                   orderby item.nIndex ascending
                                                   select item).ToList<FIFPAppointment>();
                    if (unitType != FIFPConstants.UNITTYPE_TOWER && unitType != FIFPConstants.UNITTYPE_PIPELINE && unitType != FIFPConstants.UNITTYPE_WELL && unitType != FIFPConstants.UNITTYPE_RADIAL)
                    {
                        if (plans.Count > 1)
                            CheckOverlapForOneUnit(plans, unitName, unitType, new List<string>() { unitName });
                    }
                    else if (unitType == FIFPConstants.UNITTYPE_RADIAL || unitType == FIFPConstants.UNITTYPE_TOWER || unitType == FIFPConstants.UNITTYPE_WELL)
                    {
                        //OverlapGroup overlapUnit =  OverlapLocations.Where(s => s.OverlapLocation == unitName).FirstOrDefault();
                        //if (overlapUnit == null)
                        {
                            bool bRet = CheckOverlapForRadialTowerAndWell(unitType, unitName, false);
                        }
                    }
                    else if (unitType == FIFPConstants.UNITTYPE_PIPELINE || unitType == FIFPConstants.UNITTYPE_WELL)
                    {
                        if (unitName == FIFPConstants.UNITTYPE_MOL || unitName == FIFPConstants.UNITTYPE_BYPASS_MOL)
                        {
                            if (plans.Count > 1)
                                CheckOverlapForOneUnit(plans, unitName, unitType, new List<string>() { unitName });
                        }
                        else if (unitName != FIFPConstants.UNITTYPE_MOL && unitName != FIFPConstants.UNITTYPE_BYPASS_MOL && unitType != FIFPConstants.UNITTYPE_WELL)//Pipeline
                        {
                            Unit unit = UnitList.Where(s => s.UnitName == unitName).FirstOrDefault();
                            if (unit != null && unit.FluidType == FIFPConstants.FLUIDTYPE_GAS)
                                CheckOverlapForRadialAndGasPipeline(unitType, unitName);
                            else
                                OverlapCheckingForPipeline(unitType, unitName);
                        }
                    }
                }
            }
            if (OverlapLocations != null && OverlapLocations.Count > 0)
            {
                foreach (OverlapGroup group in OverlapLocations)
                    group.nIndex = (group.OverlapLocation == FIFPConstants.UNITTYPE_MOL && group.OverlapType == FIFPConstants.UNITTYPE_PIPELINE) ? 1 : (group.OverlapType == FIFPConstants.UNITTYPE_USSC_PLATFORM) ? 2 : (group.OverlapLocation == FIFPConstants.UNITTYPE_BYPASS_MOL && group.OverlapType == FIFPConstants.UNITTYPE_PIPELINE) ? 3 : (group.OverlapType == FIFPConstants.UNITTYPE_PLATFORM) ? 4 : (group.OverlapType == FIFPConstants.UNITTYPE_COMPRESSOR) ? 5 : (group.OverlapType == FIFPConstants.UNITTYPE_SEPERATOR) ? 6 : (group.OverlapType == FIFPConstants.UNITTYPE_MODULE) ? 7 : (group.OverlapType == FIFPConstants.UNITTYPE_SPHEROID) ? 8 : (group.OverlapType == FIFPConstants.UNITTYPE_STRIPPER) ? 9 : (group.OverlapType == FIFPConstants.UNITTYPE_RADIAL) ? 10 : (group.OverlapType == FIFPConstants.UNITTYPE_TOWER) ? 11 : (group.OverlapType == FIFPConstants.UNITTYPE_PIPELINE) ? 12 : (group.OverlapType == FIFPConstants.UNITTYPE_WELL) ? 13 : (group.OverlapType == FIFPConstants.UNITTYPE_STRING ? 14 : 0);
                OverlapLocations = new ObservableCollection<OverlapGroup>(from item in OverlapLocations
                                                                          orderby item.nIndex ascending
                                                                          select item);
            }
        }

        private bool CheckOverlapForRadialTowerAndWell(string unitType, string unitName, bool bUpdate)
        {
            List<FIFPAppointment> plans = new List<FIFPAppointment>();
            List<string> overlapUnits = new List<string>();
            Unit locationTowerUnit = null;
            Unit towerUnit = null;

            overlapUnits.Add(unitName); //1. Add the current location in overlapUnits list.

            if (unitType == FIFPConstants.UNITTYPE_RADIAL)  //2. Find out tower unit for selected location(Radial,tower,well)
            {
                Unit radialUnit = UnitList.Where(s => s.UnitName == unitName).FirstOrDefault();
                if (radialUnit != null)
                    towerUnit = UnitList.Where(s => s.ParentUnitID == radialUnit.UnitID).FirstOrDefault();
            }
            else if (unitType == FIFPConstants.UNITTYPE_TOWER)
            {
                towerUnit = UnitList.Where(s => s.UnitName == unitName).FirstOrDefault();
            }
            else if (unitType == FIFPConstants.UNITTYPE_WELL)
            {
                towerUnit = FindParentUnit(UnitList.Where(s => s.UnitName == unitName).FirstOrDefault());
            }

            if (towerUnit != null && towerUnit.UnitType == FIFPConstants.UNITTYPE_TOWER) //3.Find out normal and alfa tower
            {
                string towerName = string.Empty;
                string alfaTowerName = string.Empty;
                if (towerUnit.UnitName.LastIndexOf('A') > 0)//Alfa tower
                {
                    alfaTowerName = towerUnit.UnitName;
                    towerName = towerUnit.UnitName.Substring(0, towerUnit.UnitName.LastIndexOf('A'));
                }
                else
                {
                    alfaTowerName = towerUnit.UnitName + "A";
                    towerName = towerUnit.UnitName;
                }

                List<string> towerPlans = new List<string>(); //4. Add normal and alfa tower to this list if exists
                towerPlans.Add(towerName);
                towerPlans.Add(alfaTowerName);

                FIFPAppointment normalPlan = OverlapOriginalPlans.Where(s => s.UnitName == towerName).FirstOrDefault();
                if (!string.IsNullOrEmpty(towerName) && normalPlan != null)
                {
                    overlapUnits.Add(towerName);//Normal tower
                    FIFPAppointment alphaPlan = OverlapOriginalPlans.Where(s => s.UnitName == alfaTowerName).FirstOrDefault();
                    if (alphaPlan != null)
                    {
                        overlapUnits.Add(alfaTowerName);//Alfa tower
                    }
                }
                else
                {
                    FIFPAppointment alphaPlan = OverlapOriginalPlans.Where(s => s.UnitName == alfaTowerName).FirstOrDefault();
                    if (alphaPlan != null)
                    {
                        overlapUnits.Add(alfaTowerName);//Alfa tower
                    }
                }

                towerUnit = UnitList.Where(s => s.UnitName == towerName).FirstOrDefault();//Anyway we add normal tower as location

                if (towerPlans != null && towerPlans.Count > 0)
                {
                    foreach (string tower in towerPlans)
                    {
                        List<Unit> towerUnits = UnitList.Where(s => s.UnitName == tower).ToList<Unit>();
                        if (towerUnits != null && towerUnits.Count > 0)
                        {
                            foreach (Unit unit in towerUnits)
                            {
                                Unit radialUnit = UnitList.Where(s => s.UnitID == unit.ParentUnitID).FirstOrDefault();
                                if (radialUnit != null)
                                    overlapUnits.Add(radialUnit.UnitName);
                            }
                        }

                        List<string> towelWellUnits = UnitList.Where(s => tower.Equals(s.UnitName) && s.ChildUnitList != null).SelectMany(s => s.ChildUnitList).Where(m => m.UnitType == FIFPConstants.UNITTYPE_WELL).ToList<Unit>().Select(s => s.UnitName).Distinct().ToList<string>();
                        overlapUnits.AddRange(towelWellUnits);//Get tower child units = well
                        overlapUnits.AddRange(UnitList.Where(s => tower.Equals(s.UnitName) && s.ChildUnitList != null).SelectMany(s => s.ChildUnitList).Where(m => m.UnitType == FIFPConstants.UNITTYPE_PIPELINE).ToList<Unit>().Select(s => s.UnitName).Distinct().ToList<string>());//pipeline units
                        overlapUnits.AddRange(UnitList.Where(s => towelWellUnits.Any(p => p.Equals(s.UnitName) && s.ChildUnitList != null)).SelectMany(s => s.ChildUnitList).Select(s => s.UnitName).Distinct().ToList<string>());//well string units
                    }
                }
            }
            if (towerUnit != null)
            {
                locationTowerUnit = towerUnit;
            }
            overlapUnits = overlapUnits.Distinct().ToList<string>();
            bool bRet = false;

            plans = new List<FIFPAppointment>();
            plans.AddRange(OverlapOriginalPlans.Where(t => overlapUnits.Any(s => s.Equals(t.UnitName))));

            bRet = CheckOverlapForTowerUnit(plans, locationTowerUnit.UnitName, locationTowerUnit.UnitType, false);
            if (bRet)
            {
                OverlapGroup overlapGroup = new OverlapGroup(locationTowerUnit.UnitName, locationTowerUnit.UnitType, overlapUnits);
                if (!OverlapLocations.Contains(overlapGroup) && !bUpdate)
                    OverlapLocations.Add(overlapGroup);

                OverlapGrouping(GetSortList((from item in OverlapOriginalPlans
                                             where overlapUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                             select item).ToList<FIFPAppointment>()));
            }
            return bRet;
        }

        private void CheckOverlapForRadialAndGasPipeline(string unitType, string unitName)
        {
            List<string> overlapUnits = new List<string>();
            //List<string> towerUnitNames = UnitList.Where(s => s.UnitName.Equals(unitName) && s.ChildUnitList != null).SelectMany(s => s.ChildUnitList).ToList<Unit>().Select(s => s.UnitName).Distinct().ToList<string>();//Get radial child units = tower 
            Unit pipelineUnit = UnitList.Where(s => s.UnitName == unitName).FirstOrDefault();
            if (pipelineUnit != null)
            {
                Unit towerUnit = UnitList.Where(s => s.ParentUnitID == pipelineUnit.UnitID).FirstOrDefault();
                if (towerUnit != null)
                {
                    overlapUnits.Add(towerUnit.UnitName);
                    overlapUnits.AddRange(towerUnit.ChildUnitList.Select(s => s.UnitName));//Get radial child units = well
                }

                overlapUnits.Add(unitName);

                if (overlapUnits != null && overlapUnits.Count > 0)
                {
                    List<FIFPAppointment> overlapEligiblePlans = new List<FIFPAppointment>();
                    overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => overlapUnits.Any(s => s.Equals(t.UnitName))));
                    if (overlapEligiblePlans.Count > 1)
                    {
                        CheckOverlapForOneUnit(overlapEligiblePlans, towerUnit.UnitName, towerUnit.UnitType, overlapUnits);
                    }
                }
            }
        }

        private bool OverlapCheckingForPipeline(string unitType, string unitName)
        {
            List<string> overlapUnits = new List<string>();
            overlapUnits.Add(unitName);
            ////Pipeline with Parent tower overlap checking
            Unit parentTowerUnit = FindParentUnit(UnitList.Where(s => s.UnitName == unitName).FirstOrDefault());
            if (parentTowerUnit != null && parentTowerUnit.UnitType == FIFPConstants.UNITTYPE_TOWER)
            {
                if (parentTowerUnit.UnitName.LastIndexOf('A') > 0)//Alfa tower
                {
                    overlapUnits.Add(parentTowerUnit.UnitName);
                    string normalTower = parentTowerUnit.UnitName.Substring(0, parentTowerUnit.UnitName.LastIndexOf('A'));
                    FIFPAppointment normalPlan = OverlapOriginalPlans.Where(s => s.UnitName == normalTower).FirstOrDefault();
                    if (!string.IsNullOrEmpty(normalTower) && normalPlan != null)
                    {
                        overlapUnits.Add(normalTower);
                    }
                }
                else
                {
                    string alfaTower = parentTowerUnit.UnitName + "A";
                    overlapUnits.Add(parentTowerUnit.UnitName);
                    FIFPAppointment alphaPlan = OverlapOriginalPlans.Where(s => s.UnitName == alfaTower).FirstOrDefault();
                    if (alphaPlan != null)
                    {
                        overlapUnits.Add(alfaTower);
                    }
                }
            }
            Unit radialUnit = UnitList.Where(s => s.UnitID == parentTowerUnit.ParentUnitID).FirstOrDefault();
            if (radialUnit != null)
                overlapUnits.Add(radialUnit.UnitName);
            List<string> parentTowerChildUnits = parentTowerUnit.ChildUnitList.Where(p => p.UnitType == FIFPConstants.UNITTYPE_WELL).Select(s => s.UnitName).Distinct().ToList<string>();
            overlapUnits.AddRange(parentTowerChildUnits);
            overlapUnits.AddRange(UnitList.Where(s => parentTowerChildUnits.Any(p => p.Equals(s.UnitName) && s.ChildUnitList != null)).SelectMany(s => s.ChildUnitList).Select(s => s.UnitName).Distinct().ToList<string>());//well string units
            bool isOverLap = false;
            List<FIFPAppointment> overlapEligiblePlans = new List<FIFPAppointment>();
            overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => overlapUnits.Any(s => s.Equals(t.UnitName))));
            if (overlapEligiblePlans.Count > 1)
            {
                isOverLap = FlagOverlappedPlans(GetSortList(overlapEligiblePlans));
            }

            bool pipelineWithParentOverlap = false;

            List<FIFPAppointment> pipelineOverlappedWithParentPlans = overlapEligiblePlans.Where(s => s.UnitType == FIFPConstants.UNITTYPE_PIPELINE && s.IsOverlapped == true).ToList<FIFPAppointment>();
            if (pipelineOverlappedWithParentPlans != null && pipelineOverlappedWithParentPlans.Count > 0)
                pipelineWithParentOverlap = true;
            else
            {
                overlapUnits = new List<string>();
                overlapUnits.Add(unitName);
            }

            //Pipeline with Child tower overlap checking


            List<string> overlapChildUnits = new List<string>();
            overlapChildUnits.Add(unitName);
            List<Unit> pipelineChildTowerUnits = UnitList.Where(s => s.UnitName == unitName && s.ChildUnitList != null).SelectMany(s => s.ChildUnitList).Where(p => p.UnitType == FIFPConstants.UNITTYPE_TOWER).ToList<Unit>();//Get Pipeline child tower units
            List<string> pipeLineTowerUnits = new List<string>();
            if (pipelineChildTowerUnits != null && pipelineChildTowerUnits.Count > 0)
            {
                foreach (Unit towerUnit in pipelineChildTowerUnits)
                {
                    if (towerUnit.UnitName.LastIndexOf('A') > 0)//Alfa tower
                    {
                        string normalTower = towerUnit.UnitName.Substring(0, towerUnit.UnitName.LastIndexOf('A'));
                        FIFPAppointment normalPlan = OverlapOriginalPlans.Where(s => s.UnitName == normalTower).FirstOrDefault();
                        if (!string.IsNullOrEmpty(normalTower) && normalPlan == null)
                        {
                            pipeLineTowerUnits.Add(towerUnit.UnitName);
                        }
                    }
                    else
                    {
                        string alfaTower = towerUnit.UnitName + "A";
                        pipeLineTowerUnits.Add(towerUnit.UnitName);
                        FIFPAppointment alphaPlan = OverlapOriginalPlans.Where(s => s.UnitName == alfaTower).FirstOrDefault();
                        if (alphaPlan != null)
                        {
                            pipeLineTowerUnits.Add(alfaTower);
                        }
                    }
                }

            }
            List<string> pipelineChildTowerChildUnits = UnitList.Where(p => pipeLineTowerUnits.Any(s => s.Equals(p.UnitName)) && p.ChildUnitList != null).SelectMany(s => s.ChildUnitList).Where(p => p.UnitType == FIFPConstants.UNITTYPE_WELL).Select(s => s.UnitName).Distinct().ToList<string>();//Get child tower well units

            overlapChildUnits.AddRange(pipeLineTowerUnits);
            overlapChildUnits.AddRange(pipelineChildTowerChildUnits);
            List<string> pipelineChildTowerChildStringUnits = UnitList.Where(s => pipelineChildTowerChildUnits.Any(p => p.Equals(s.UnitName) && s.ChildUnitList != null)).SelectMany(s => s.ChildUnitList).Select(s => s.UnitName).Distinct().ToList<string>();//well string units
            overlapChildUnits.AddRange(pipelineChildTowerChildStringUnits);
            
            overlapUnits.AddRange(pipeLineTowerUnits);
            overlapUnits.AddRange(pipelineChildTowerChildUnits);
            overlapUnits.AddRange(pipelineChildTowerChildStringUnits);

            overlapEligiblePlans = new List<FIFPAppointment>();
            overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => overlapChildUnits.Any(s => s.Equals(t.UnitName))));
            bool bRet = false;
            if (overlapEligiblePlans.Count > 1)
            {
                bRet = FlagOverlappedPlans(GetSortList(overlapEligiblePlans));
                if (bRet)
                    isOverLap = bRet;
            }

            bool pipelineWithChildOverlap = false;
            if (bRet)
            {
                List<FIFPAppointment> pipelineOverlappedWithChildPlans = overlapEligiblePlans.Where(s => s.UnitType == FIFPConstants.UNITTYPE_PIPELINE && s.IsOverlapped == true).ToList<FIFPAppointment>();
                if (pipelineOverlappedWithChildPlans != null && pipelineOverlappedWithChildPlans.Count > 0)
                    pipelineWithChildOverlap = true;
            }

            if (pipelineWithParentOverlap && pipelineWithChildOverlap) //If pipeline with parent tower overlap is true then we no need to check the below.
                isOverLap = true;
            else
                isOverLap = false;

            if (isOverLap)
            {
                OverlapGroup overlapGroup = new OverlapGroup(unitName, unitType, overlapUnits);
                if (!OverlapLocations.Contains(overlapGroup))
                    OverlapLocations.Add(overlapGroup);

                OverlapGrouping(GetSortList((from item in OverlapOriginalPlans
                                             where overlapUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                             select item).ToList<FIFPAppointment>()));
            }
            return isOverLap;
        }

        private bool GenerateTowerOverlapActivities(string unitName, string unitType, bool bUpdate, List<string> towerUnitNames)
        {
            bool isOverlapped = false;
            List<string> pipelineUnits = UnitList.Where(s => towerUnitNames.Any(t => t.Equals(s.UnitName) && s.ChildUnitList != null)).SelectMany(s => s.ChildUnitList).ToList<Unit>().Where(p => p.UnitType == FIFPConstants.UNITTYPE_PIPELINE).Select(s => s.UnitName).Distinct().ToList<string>();//Get Pipeline units
            List<string> towerChildUnits = UnitList.Where(s => towerUnitNames.Any(t => t.Equals(s.UnitName) && s.ChildUnitList != null)).SelectMany(s => s.ChildUnitList).ToList<Unit>().Where(p => p.UnitType != FIFPConstants.UNITTYPE_PIPELINE).Select(s => s.UnitName).Distinct().ToList<string>();//Get Tower and Well units
            List<string> towerWithChildUnits = new List<string>();
            if (pipelineUnits != null && pipelineUnits.Count > 0)
            {

                towerWithChildUnits.AddRange(towerUnitNames);
                towerWithChildUnits.AddRange(towerChildUnits);
                towerWithChildUnits.AddRange(pipelineUnits);
                foreach (string pipeline in pipelineUnits)
                {
                    List<string> overlapUnits = new List<string>();
                    overlapUnits.Add(pipeline);
                    overlapUnits.AddRange(towerChildUnits);
                    List<FIFPAppointment> overlapEligiblePlans = new List<FIFPAppointment>();
                    overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => towerUnitNames.Any(s => s.Equals(t.UnitName))));
                    overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => overlapUnits.Any(s => s.Equals(t.UnitName))));

                    bool bRet = CheckOverlapForTowerUnit(overlapEligiblePlans, unitName, unitType, bUpdate);
                    if (bRet)
                        isOverlapped = bRet;
                    if (bRet)
                    {
                        OverlapGroup overlapGroup = new OverlapGroup(unitName, unitType, towerWithChildUnits);
                        if (!OverlapLocations.Contains(overlapGroup) && !bUpdate)
                            OverlapLocations.Add(overlapGroup);
                    }
                }
            }
            else
            {
                List<FIFPAppointment> overlapEligiblePlans = new List<FIFPAppointment>();
                overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => towerUnitNames.Any(s => s.Equals(t.UnitName))));
                overlapEligiblePlans.AddRange(OverlapOriginalPlans.Where(t => towerChildUnits.Any(s => s.Equals(t.UnitName))));
                towerWithChildUnits.AddRange(towerUnitNames);
                towerWithChildUnits.AddRange(towerChildUnits);
                isOverlapped = CheckOverlapForTowerUnit(overlapEligiblePlans, unitName, unitType, bUpdate);
                if (isOverlapped)
                {
                    OverlapGroup overlapGroup = new OverlapGroup(unitName, unitType, towerWithChildUnits);
                    if (!OverlapLocations.Contains(overlapGroup) && !bUpdate)
                        OverlapLocations.Add(overlapGroup);
                }
            }

            if (isOverlapped)
            {
                OverlapGrouping(GetSortList((from item in OverlapOriginalPlans
                                             where towerWithChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                             select item).ToList<FIFPAppointment>()));
            }
            return isOverlapped;
        }

        private Unit FindParentUnit(Unit childUnit)
        {
            Unit unit = UnitList.Where(s => s.UnitID == childUnit.UnitID).FirstOrDefault();
            GetUnitNameList(unit);
            return TowerUnit;
        }

        private void GetUnitNameList(Unit unit)
        {
            Unit childUnit = UnitList.Where(p => p.UnitID == unit.ParentUnitID).FirstOrDefault();
            if (childUnit != null)
            {
                if (childUnit.UnitType != FIFPConstants.UNITTYPE_TOWER)
                    GetUnitNameList(childUnit);
                else
                    TowerUnit = childUnit;
            }
        }

        //check overlap plans for one unit
        private void CheckOverlapForOneUnit(List<FIFPAppointment> planList, string unitName, string unitType, List<string> childUnits)
        {
            //If it is single unit(Radial, Compressor, Separator, Module, Spheroid, Stripper) we can directly call FlagOverlappedPlans fucntion
            bool bRet = FlagOverlappedPlansForSingleUnit(GetSortList(planList));
            if (bRet)
            {
                OverlapGroup overlapGroup = new OverlapGroup(unitName, unitType, childUnits);
                if (!OverlapLocations.Contains(overlapGroup))
                    OverlapLocations.Add(overlapGroup);
            }
        }

        private bool CheckOverlapForTowerUnit(List<FIFPAppointment> planList, string unitName, string unitType, bool bUpdate)
        {
            bool isOverlapped = false;
            bool isTowerChecked = false;
            List<string> childUnits = planList.Select(s => s.UnitName).Distinct().ToList<string>();

            List<FIFPAppointment> wellPlans = planList.Where(t => t.UnitType == FIFPConstants.UNITTYPE_WELL || t.UnitType == FIFPConstants.UNITTYPE_STRING).ToList<FIFPAppointment>();
            List<FIFPAppointment> pipelinePlans = planList.Where(t => t.UnitType == FIFPConstants.UNITTYPE_PIPELINE || t.UnitType == FIFPConstants.UNITTYPE_RADIAL).ToList<FIFPAppointment>();
            List<FIFPAppointment> towerPlans = planList.Where(t => t.UnitType == FIFPConstants.UNITTYPE_TOWER).ToList<FIFPAppointment>();

            bool bRet = false;
            //Overlap checking for Tower and Well               
            List<FIFPAppointment> overlapCheckingPlans = new List<FIFPAppointment>();
            if (wellPlans != null && wellPlans.Count > 0)
            {
                if (towerPlans.Count > 0)
                    isTowerChecked = true;
                overlapCheckingPlans.AddRange(towerPlans);
                overlapCheckingPlans.AddRange(wellPlans);
                bRet = FlagOverlappedPlans(GetSortList(overlapCheckingPlans));
                if (bRet)
                    isOverlapped = bRet;


            }

            //Overlap checking for Tower and Pipeline
            overlapCheckingPlans = new List<FIFPAppointment>();
            if (pipelinePlans != null && pipelinePlans.Count > 0)
            {
                if (towerPlans.Count > 0)
                    isTowerChecked = true;
                overlapCheckingPlans.AddRange(towerPlans);
                overlapCheckingPlans.AddRange(from item in pipelinePlans
                                              where (item.UnitType == FIFPConstants.UNITTYPE_RADIAL || item.UnitType == FIFPConstants.UNITTYPE_PIPELINE) && item.ActivityCode != FIFPConstants.ACTIVITY_TYPE_MTN_SS
                                              select item);
                bRet = FlagOverlappedPlans(GetSortList(overlapCheckingPlans));
                if (bRet)
                    isOverlapped = bRet;

            }
            //Overlap checking for Well and Pipeline
            overlapCheckingPlans = new List<FIFPAppointment>();
            if (wellPlans.Count > 0 && pipelinePlans.Count > 0)
            {
                if (pipelinePlans.Count > 0 && pipelinePlans.Where(s => (s.UnitType == FIFPConstants.UNITTYPE_RADIAL || s.UnitType == FIFPConstants.UNITTYPE_PIPELINE) && s.ActivityCode == FIFPConstants.ACTIVITY_TYPE_MTN_SS).Count() > 0)
                {
                    overlapCheckingPlans.AddRange(from item in wellPlans
                                                  where item.ActivityCode != FIFPConstants.ACTIVITY_TYPE_RIG && item.ActivityCode != FIFPConstants.ACTIVITY_TYPE_RGL
                                                  select item);
                }
                else
                    overlapCheckingPlans.AddRange(wellPlans);

                overlapCheckingPlans.AddRange(from item in pipelinePlans
                                              where (item.UnitType == FIFPConstants.UNITTYPE_RADIAL || item.UnitType == FIFPConstants.UNITTYPE_PIPELINE) && item.ActivityCode != FIFPConstants.ACTIVITY_TYPE_MTN_SS
                                              select item);
                bRet = FlagOverlappedPlans(GetSortList(overlapCheckingPlans));
                if (bRet)
                    isOverlapped = bRet;

            }
            //Overlap checking for Pipeline  
            if (pipelinePlans != null && pipelinePlans.Count > 0)
            {

                bRet = FlagOverlappedPlans(GetSortList(pipelinePlans));
                if (bRet)
                    isOverlapped = bRet;
            }
            //Overlap checking for Tower
            if (!isTowerChecked && towerPlans.Count > 0)
            {
                bRet = FlagOverlappedPlans(GetSortList(towerPlans));
                if (bRet)
                    isOverlapped = bRet;

            }

            return isOverlapped;
        }

        private void OverlapLocationGridRowLoad(object e)
        {
            DataGridRowEventArgs eventargs = e as DataGridRowEventArgs;
            if (eventargs != null)
            {
                OverlapGroup group = eventargs.Row.DataContext as OverlapGroup;
                if (group != null && SelectedOverlapLocation != null)
                {
                    if (group == SelectedOverlapLocation)
                    {
                        eventargs.Row.Background = new SolidColorBrush(new Color() { R = 0x90, G = 0xEE, B = 0x90, A = 0xFF });
                    }
                }
            }
        }

        private void OverlapLocationGridSelectionChange(DataGrid locationGrid)
        {
            if (locationGrid != null && locationGrid.SelectedItem != null)
            {
                LocationGrid = locationGrid;
                IsApplySimopsButtonEnabled = false;
                ModifiedActivities = new ObservableCollection<FIFPAppointment>();
                SelectedOverlapLocation = locationGrid.SelectedItem as OverlapGroup;
                if (SelectedOverlapLocation != null)
                {

                    List<FIFPAppointment> lstModifiedActivities = new List<FIFPAppointment>();
                    if (SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_TOWER)
                    {
                        SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                                      where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                                                                                      orderby item.Overlap_Id ascending
                                                                                                      select item).ToList<FIFPAppointment>());
                        if (SelectedUnitOverlappedActivities.Count == 0)
                        {
                            //IsCheckOverlapButtonEnabled = false;
                            SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                                          where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == false && item.Overlap_Id > 0
                                                                                                          orderby item.Overlap_Id ascending
                                                                                                          select item));
                        }
                        //else
                        //    IsCheckOverlapButtonEnabled = true;
                    }
                    else
                    {
                        SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                                      where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                                                                                      orderby item.Overlap_Id ascending
                                                                                                      select item).ToList<FIFPAppointment>());
                        if (SelectedUnitOverlappedActivities.Count == 0)
                        {
                            SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                                          where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == false && item.Overlap_Id > 0
                                                                                                          orderby item.Overlap_Id ascending
                                                                                                          select item));
                        }
                        //else
                        //    IsCheckOverlapButtonEnabled = true;
                    }

                    BindGridsAndScheduleView();

                    CheckOverlapByLocation(false);
                }

            }
        }

        private void BindGridsAndScheduleView()
        {
            if (SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_TOWER)
            {
                SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                              where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                                                                              orderby item.Overlap_Id ascending
                                                                                              select item).ToList<FIFPAppointment>());
                if (SelectedUnitOverlappedActivities.Count == 0)
                {
                    //IsCheckOverlapButtonEnabled = false;
                    SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                                  where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == false && item.Overlap_Id > 0
                                                                                                  orderby item.Overlap_Id ascending
                                                                                                  select item));
                }
                List<FIFPAppointment> overlappedPlans = (from item in OverlapOriginalPlans
                                                         where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                                         orderby item.Overlap_Id ascending, item.RadioButtonVisibility ascending
                                                         select item).ToList<FIFPAppointment>();

                List<int> overlapWithApplySIMOPSGroup = overlappedPlans.Where(s => s.IsAppliedSimops == false).Select(p => p.Overlap_Id).ToList<int>();
                OverlappedActivities = new ObservableCollection<FIFPAppointment>(overlappedPlans.Where(s => overlapWithApplySIMOPSGroup.Any(p => p.Equals(s.Overlap_Id))).ToList<FIFPAppointment>());
                //List<FIFPAppointment> lstAppliedSIMOPS = overlappedPlans.Where(s => s.IsAppliedSimops == true).ToList<FIFPAppointment>();
                //if (overlappedPlans.Count == lstAppliedSIMOPS.Count)
                //    OverlappedActivities = new ObservableCollection<FIFPAppointment>();
                //else
                //    OverlappedActivities = new ObservableCollection<FIFPAppointment>(overlappedPlans);



                SelectedAppointments = (from item in OverlapOriginalPlans
                                        where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName))
                                        orderby item.nIndex descending
                                        select item).ToList<FIFPAppointment>();
            }
            else
            {
                SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                              where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                                                                              orderby item.Overlap_Id ascending
                                                                                              select item).ToList<FIFPAppointment>());
                if (SelectedUnitOverlappedActivities.Count == 0)
                {
                    SelectedUnitOverlappedActivities = new ObservableCollection<FIFPAppointment>((from item in OverlapOriginalPlans
                                                                                                  where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == false && item.Overlap_Id > 0
                                                                                                  orderby item.Overlap_Id ascending
                                                                                                  select item));
                }

                List<FIFPAppointment> overlappedPlans = (from item in OverlapOriginalPlans
                                                         where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName)) && item.IsOverlapped == true
                                                         orderby item.Overlap_Id ascending, item.RadioButtonVisibility ascending
                                                         select item).ToList<FIFPAppointment>();
                List<FIFPAppointment> lstAppliedSIMOPS = overlappedPlans.Where(s => s.IsAppliedSimops == true).ToList<FIFPAppointment>();
                if (overlappedPlans.Count == lstAppliedSIMOPS.Count)
                    OverlappedActivities = new ObservableCollection<FIFPAppointment>();
                else
                    OverlappedActivities = new ObservableCollection<FIFPAppointment>(overlappedPlans);

                SelectedAppointments = (from item in OverlapOriginalPlans
                                        where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName))
                                        orderby item.nIndex descending
                                        select item).ToList<FIFPAppointment>();
            }


            List<FIFPAppointment> lstAppliedSIMOPSUnits = OverlapOriginalPlans.Where(s => SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(s.UnitName)) && s.IsOverlapped == true && s.IsAppliedSimops == true).ToList<FIFPAppointment>();
            List<FIFPAppointment> lstModifiedActivities = lstAppliedSIMOPSUnits;

            //List<FIFPAppointment> lstRemovedModifiedUnits = ModifiedActivities.Where(s => s.IsOverlapped == false && s.IsAppliedSimops == false).ToList<FIFPAppointment>();
            //lstModifiedActivities.AddRange(lstRemovedModifiedUnits);

            List<FIFPAppointment> lstOverlappedUnits = SelectedLocationOverlapList.Where(s => SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(s.UnitName)) && s.IsOverlapped == true && s.IsAppliedSimops == false).ToList<FIFPAppointment>();
            //List<FIFPAppointment> lstFinalList = SelectedLocationOverlapList.Intersect(lstRemovedUnits).ToList<FIFPAppointment>();
            lstOverlappedUnits.ForEach(s => { s.ModificationReason = string.Empty; s.IsOverlapRemoved = false; });

            List<FIFPAppointment> lstRemovedUnits = SelectedLocationOverlapList.Where(s => SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(s.UnitName)) && s.IsOverlapped == false && s.IsAppliedSimops == false).ToList<FIFPAppointment>();
            //List<FIFPAppointment> lstFinalList = SelectedLocationOverlapList.Intersect(lstRemovedUnits).ToList<FIFPAppointment>();
            lstRemovedUnits.ForEach(s => { s.ModificationReason = FIFPConstants.OVERLAP_REMOVE_TEXT; s.IsOverlapRemoved = true; });

            //lstModifiedActivities.AddRange(lstFinalList);
            List<FIFPAppointment> lstRemoveOverlaps = OverlapOriginalPlans.Where(s => SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(s.UnitName)) && s.IsOverlapped == false && s.ModificationReason == FIFPConstants.OVERLAP_REMOVE_TEXT).ToList<FIFPAppointment>();
            lstModifiedActivities.AddRange(lstRemoveOverlaps);

            //lstModifiedActivities.ForEach(p => { p.RadioButtonVisibility = Visibility.Collapsed; p.ModificationReason = FIFPConstants.OVERLAP_REMOVE_TEXT; });
            foreach (FIFPAppointment appointment in lstModifiedActivities)//For apply SIMOPS, we won't change the radio button visibility and modification reason text. Only remove overlap, we can apply modification reason.
            {
                if (!appointment.IsAppliedSimops)
                {
                    appointment.SIMOPSRadioButtonVisibility = Visibility.Collapsed;
                    //appointment.ModificationReason = FIFPConstants.OVERLAP_REMOVE_TEXT;
                }
                else
                {
                    appointment.SIMOPSRadioButtonVisibility = appointment.IsRDVisibility ? Visibility.Visible : Visibility.Collapsed;
                    appointment.ModificationReason = FIFPConstants.APPLY_SIMOPS_TEXT;
                }
            }
            lstModifiedActivities = (from item in lstModifiedActivities
                                     orderby item.DB_OverlapId ascending, item.SIMOPSRadioButtonVisibility ascending
                                     select item).ToList<FIFPAppointment>();
            ModifiedActivities = new ObservableCollection<FIFPAppointment>(lstModifiedActivities);

            LoadOverlapPlans((from item in SelectedAppointments orderby item.nIndex ascending select item).ToList<FIFPAppointment>());
        }

        public void UndoOverlapActivities()
        {
            if (SelectedAppointments != null && SelectedAppointments.Count > 0 && SelectedAppointments.Where(s => s.ActivityLevel > 1).Count() > 0)
            {
                foreach (FIFPAppointment appointment in SelectedAppointments.Where(s => s.ActivityLevel > 1))
                {
                    appointment.Start = appointment.ModifiedStart;
                    appointment.End = appointment.ModifiedEnd;
                }
                LoadOverlapPlans((from item in SelectedAppointments orderby item.nIndex ascending select item).ToList<FIFPAppointment>());
            }
        }

        private void CheckOverlapForSelectedLocation(Button btnCheck)
        {
            if (SelectedOverlapLocation != null)
            {
                SelectedLocationOverlapList = SelectedAppointments.Where(s => SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(s.UnitName)) && s.IsOverlapped == true && s.IsAppliedSimops == false).ToList<FIFPAppointment>();
                //List<FIFPAppointment> lstOverlappedUnits = SelectedLocationOverlapList.Where(s => s.IsOverlapped == true && s.IsAppliedSimops == false).ToList<FIFPAppointment>();
                //lstOverlappedUnits.ForEach(s => { s.ModificationReason = string.Empty; });
                CheckOverlapByLocation(true);
            }
        }

        private void CheckOverlapByLocation(bool isPopupShow)
        {
            if (SelectedOverlapLocation != null)
            {

            }
            //if (SelectedAppointments != null && SelectedAppointments.Count > 1)
            {
                SelectedAppointments.ForEach(p => { p.IsOverlapped = false; });
                bool bRet = false;
                if (SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_TOWER)
                {
                    //bRet = CheckOverlapForTowerUnit(SelectedAppointments.Where(s => s.IsAppliedSimops == false).ToList<FIFPAppointment>(), SelectedOverlapLocation.OverlapLocation, SelectedOverlapLocation.OverlapType, true);
                    List<string> towerUnitNames = new List<string>();
                    //Check whether the radial/pipeline exists or not. If exits then we add it as tower overlap.
                    /*Unit unit = UnitList.Where(s => s.UnitName == SelectedOverlapLocation.OverlapLocation).FirstOrDefault();
                    if (unit != null)
                    {
                        Unit parentUnit = UnitList.Where(s => s.UnitID == unit.ParentUnitID).FirstOrDefault();
                        if (parentUnit != null)
                        {
                            towerUnitNames.Add(parentUnit.UnitName);
                        }
                    }*/
                    towerUnitNames.Add(SelectedOverlapLocation.OverlapLocation);
                    FIFPAppointment alfaTower = OverlapOriginalPlans.Where(s => s.UnitName == (SelectedOverlapLocation.OverlapLocation + "A")).FirstOrDefault();
                    if (alfaTower != null)
                        towerUnitNames.Add(alfaTower.UnitName);
                    //bRet = GenerateTowerOverlapActivities(SelectedOverlapLocation.OverlapLocation, SelectedOverlapLocation.OverlapType, true, towerUnitNames);
                    bRet = CheckOverlapForRadialTowerAndWell(SelectedOverlapLocation.OverlapType, SelectedOverlapLocation.OverlapLocation, true);
                }
                else if (SelectedOverlapLocation.OverlapLocation != FIFPConstants.UNITTYPE_MOL && SelectedOverlapLocation.OverlapLocation != FIFPConstants.UNITTYPE_BYPASS_MOL && SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_PIPELINE)//Pipeline
                {
                    Unit unit = UnitList.Where(s => s.UnitName == SelectedOverlapLocation.OverlapLocation).FirstOrDefault();
                    if (unit != null && unit.FluidType == FIFPConstants.FLUIDTYPE_GAS)
                        bRet = FlagOverlappedPlansForSingleUnit(GetSortList(SelectedAppointments.Where(s => s.IsAppliedSimops == false).ToList<FIFPAppointment>()));
                    else
                        bRet = OverlapCheckingForPipeline(SelectedOverlapLocation.OverlapType, SelectedOverlapLocation.OverlapLocation);
                }
                else
                    bRet = FlagOverlappedPlansForSingleUnit(GetSortList(SelectedAppointments.Where(s => s.IsAppliedSimops == false).ToList<FIFPAppointment>()));
                if (bRet)
                {
                    //Show message for user that still there are some overlap
                    if (isPopupShow)
                        ShowPopup(FIFPConstants.WARNINGTITLE_OVERLAP, FIFPConstants.WARNINGMESSAGE_OVERLAP);
                    //IsCheckOverlapButtonEnabled = true;
                }
                else
                {
                    //There is no overlap
                    if (isPopupShow)
                        ShowPopup(FIFPConstants.WARNINGTITLE_OVERLAP, FIFPConstants.WARNINGMESSAGE_NO_OVERLAP);
                    //IsCheckOverlapButtonEnabled = false;
                }

                //if(OverlapOriginalPlans != null && OverlapOriginalPlans.Where(o => o.IsOverlapped == true).Count() > 0)
                //    ServiceLocator.Get<MainPageVM>().IsLSDEnabled = false;
                //else
                //    ServiceLocator.Get<MainPageVM>().IsLSDEnabled = true;

                //Rebind Location Grid and Overlapped Activities Grid
                BindGridsAndScheduleView();

            }
        }
        private void ApplySimopsClicked(Button btnApply)
        {
            int maxId = OverlappedActivities.Max(m => m.Overlap_Modification_Id);
            List<FIFPAppointment> simopsActivities = OverlappedActivities.Where(s => s.Overlap_Id == SelectedOverlapId).ToList<FIFPAppointment>();
            int nIndex = 0;
            foreach (FIFPAppointment appointment in simopsActivities)
            {
                appointment.Overlap_Modification_Id = maxId + 1;
                appointment.RadioButtonVisibility = (nIndex == 0) ? Visibility.Visible : Visibility.Collapsed;
                appointment.SIMOPSRadioButtonVisibility = (nIndex == 0) ? Visibility.Visible : Visibility.Collapsed;
                appointment.DB_OverlapId = appointment.Overlap_Id;
                appointment.IsRDVisibility = appointment.RadioButtonVisibility == Visibility.Visible ? true : false;
                appointment.ModificationReason = FIFPConstants.APPLY_SIMOPS_TEXT;
                appointment.IsAppliedSimops = true;
                appointment.IsOverlapped = false;
                appointment.IsModified = appointment.IsModified == 1 ? 1 : 0;
                nIndex++;
            }
            OverlappedActivities = new ObservableCollection<FIFPAppointment>(OverlappedActivities.Where(s => s.Overlap_Id != SelectedOverlapId));
            //IsCheckOverlapButtonEnabled = (OverlappedActivities != null && OverlappedActivities.Count > 0) ? true : false;
            ModifiedActivities.AddRange(simopsActivities);
            IsApplySimopsButtonEnabled = false;
            if (SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_TOWER)
            {
                LoadOverlapPlans((from item in OverlapOriginalPlans
                                  where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName))
                                  orderby item.nIndex ascending
                                  select item).ToList<FIFPAppointment>());
            }
            else
                LoadOverlapPlans((from item in OverlapOriginalPlans
                                  where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName))
                                  orderby item.nIndex ascending
                                  select item).ToList<FIFPAppointment>());
            //ServiceLocator.Get<AppointmentVM>().Appointments.Where(w => w.Overlap_Id == SelectedOverlapId).ToList<FIFPAppointment>().ForEach(c => { c.Category = new Category("", new SolidColorBrush(Colors.Gray)); });
            //ServiceLocator.Get<AppointmentVM>().Appointments.Where(w => w.Overlap_Id == SelectedOverlapId).ToList<FIFPAppointment>().ForEach(c => { c.Category = new Category("", new SolidColorBrush(new Color() { R = 0x80, G = 0x80, B = 0x80, A = 0xFF })); });

        }
        private void CancelSimopsClicked(Button btnCancel)
        {
            List<FIFPAppointment> simopsActivities = ModifiedActivities.Where(m => m.DB_OverlapId == SelectedCancelSIMOPSOverlapId && m.IsAppliedSimops == true).ToList<FIFPAppointment>();


            List<FIFPAppointment> lstIntersecWithLeftRight = OverlappedActivities.Intersect(ModifiedActivities).ToList<FIFPAppointment>();
            if (lstIntersecWithLeftRight != null && lstIntersecWithLeftRight.Count == 0)
                OverlappedActivities.AddRange(simopsActivities);


            ModifiedActivities = new ObservableCollection<FIFPAppointment>(ModifiedActivities.Where(m => m.DB_OverlapId != SelectedCancelSIMOPSOverlapId));

            //Once done all checking we have to reset fields.
            simopsActivities.ForEach(c => { c.IsAppliedSimops = false; c.IsOverlapped = true; c.ModificationReason = string.Empty; c.DB_OverlapId = 0; c.IsRDVisibility = false; c.IsModified = (c.IsModified == 1) ? 1 : 0; });

            IsCancelSimopsButtonEnabled = false;
            CheckOverlapByLocation(false);
            //IsCheckOverlapButtonEnabled = (OverlappedActivities != null && OverlappedActivities.Count > 0) ? true : false;
            //if (SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_TOWER)
            //{
            //    LoadOverlapPlans((from item in OverlapOriginalPlans
            //                      where SelectedOverlapLocation.ChildUnits.Any(p => p.Equals(item.UnitName))
            //                      orderby item.nIndex descending
            //                      select item).ToList<FIFPAppointment>());
            //}
            //else
            //    LoadOverlapPlans((from item in OverlapOriginalPlans
            //                      where item.UnitName == SelectedOverlapLocation.OverlapLocation
            //                      orderby item.nIndex descending
            //                      select item).ToList<FIFPAppointment>());
        }
        private void IsApplicableForCancelSIMOPS(RadioButton rdBtn)
        {
            if (rdBtn != null && rdBtn.Tag != null)
            {
                SelectedCancelSIMOPSOverlapId = Convert.ToInt32(rdBtn.Tag);
                IsCancelSimopsButtonEnabled = true;
            }
        }
        private void IsApplicableForApplySIMOPS(RadioButton rdBtn)
        {
            if (rdBtn != null && rdBtn.Tag != null)
            {
                SelectedOverlapId = Convert.ToInt32(rdBtn.Tag);
                if ((SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_TOWER || (SelectedOverlapLocation.OverlapLocation != FIFPConstants.UNITTYPE_MOL && SelectedOverlapLocation.OverlapLocation != FIFPConstants.UNITTYPE_BYPASS_MOL && SelectedOverlapLocation.OverlapType == FIFPConstants.UNITTYPE_PIPELINE)) && SelectedOverlapId > 0)
                {
                    if (OverlappedActivities.Where(s => s.Overlap_Id == SelectedOverlapId).Count() > 1)
                        IsApplySimopsButtonEnabled = true;
                    else
                        IsApplySimopsButtonEnabled = false;
                    /* We should apply SIMOPS for more than one activities
                    if (OverlappedActivities.Where(s => s.Overlap_Id == SelectedOverlapId).Count() == 2)
                        IsApplySimopsButtonEnabled = true;
                    else
                    {
                        IsApplySimopsButtonEnabled = false;
                        ShowPopup(FIFPConstants.WARNINGTITLE_APPLYSIMOPS, FIFPConstants.WARNINGMESSAGE_APPLYSIMOPS);
                    }*/
                }
            }
        }
        private void ShowPopup(string title, string message)
        {
            Warning warningWindow = new Warning();
            warningWindow.CancelButton.Visibility = Visibility.Collapsed;
            warningWindow.Title = title;
            warningWindow.lblMessage.Text = message;
            warningWindow.lblMessage.Visibility = Visibility.Visible;
            warningWindow.Show();
        }

        private void LoadOverlapPlans(List<FIFPAppointment> plans)
        {
            //set red for overlapped plans, green for non-overlapped plans
            foreach (FIFPAppointment appointment in plans)
            {
                appointment.Category = (appointment.IsAppliedSimops) ? new Category("", new SolidColorBrush(new Color() { R = 0x3D, G = 0x3D, B = 0x3D, A = 0xFF })) : (appointment.IsOverlapped) ? new Category("", new SolidColorBrush(Colors.Red)) : new Category("", new SolidColorBrush(Colors.Green));
            }

            AppointmentGroup appointmentGroup = new AppointmentGroup();
            List<ResourceType> lstResources = new List<ResourceType>();
            List<Resource> unitList = new List<Resource>();
            ResourceType unitType = new ResourceType("Unit");
            unitType.DisplayName = "Unit";
            unitType.Name = "Unit";

            foreach (FIFPAppointment appointment in plans)
            {
                Resource resource = new Resource() { ResourceName = appointment.UnitName, DisplayName = appointment.UnitName, ResourceType = unitType.Name };
                //unitList.Add(resource);
                if (!unitList.Contains(resource))
                {
                    unitList.Add(resource);
                }
                appointment.Resources.Add(resource);
            }

            appointmentGroup.Appointments = new List<FIFPAppointment>(plans);
            unitType.Resources.AddRange(unitList);
            lstResources.Add(unitType);


            appointmentGroup.ResourceTypes = lstResources;
            appointmentGroup.UnitList = unitList;

            if (OnAppointmentDataCompleted != null)
                OnAppointmentDataCompleted(this, new CustomEventArgs<AppointmentGroup>(appointmentGroup));

        }

        #region Overlap Checking algrithom
        //input  : activities for one unit
        //output : a list filled with PlanForSort,  and it is sorted with all start date and end date
        private List<PlanForSort> GetSortList(List<FIFPAppointment> list)
        {
            List<PlanForSort> sortedList = new List<PlanForSort>();
            //create the list for sort
            foreach (FIFPAppointment a in list)
            {
                //flag = 1  means it is a  start date
                //flag = -1 means it is an end date
                sortedList.Add(new PlanForSort(a.PlanID, a.Start, 1));
                sortedList.Add(new PlanForSort(a.PlanID, a.End, -1));
            }
            //sort
            sortedList.Sort();
            return sortedList;
        }

        //input  : sorted list of activitiesforplan for one unit        
        private bool FlagOverlappedPlansForSingleUnit(List<PlanForSort> list)
        {
            bool returnFlag = false;
            int sumFlag = 0;
            List<FIFPAppointment> tempList = new List<FIFPAppointment>();

            foreach (PlanForSort plan in list)
            {
                //sumflag == 0 means it is a new overlap group, so 
                //create a new list for activities in this overlap group
                //add the current activity
                //add the list to the result 
                if (sumFlag == 0)
                {
                    List<FIFPAppointment> lstAppointment = new List<FIFPAppointment>();
                    lstAppointment.Add(OriginalPlansDictionary[plan.id]);

                    sumFlag += plan.flag;

                    if (tempList.Count > 1)//This is no needed. Later we have to modify.
                    {
                        overlapId++;
                        //int nIndex = 0;
                        //foreach (FIFPAppointment appointment in tempList)
                        //{
                        //    if (!appointment.IsOverlapped)
                        //    {
                        //        appointment.IsOverlapped = true;
                        //        appointment.Overlap_Id = overlapId;
                        //        appointment.RadioButtonVisibility = (nIndex == 0) ? Visibility.Visible : Visibility.Collapsed;
                        //        nIndex++;
                        //    }
                        //}
                        returnFlag = true;
                    }
                    tempList = lstAppointment;
                }
                //sumflag != 0 means it is in the process of the overlap group
                else
                {
                    if (plan.flag == 1)
                    {
                        tempList.Add(OriginalPlansDictionary[plan.id]);
                    }

                    sumFlag += plan.flag;

                    if (sumFlag == 0)
                    {
                        if (tempList.Count > 1)
                        {
                            overlapId++;
                            int nIndex = 0;
                            tempList = (from item in tempList
                                        orderby item.nIndex
                                        select item).ToList<FIFPAppointment>();
                            foreach (FIFPAppointment appointment in tempList)
                            {
                                if (!appointment.IsOverlapped)
                                {
                                    appointment.IsOverlapped = true;
                                    appointment.Overlap_Id = overlapId;
                                    //appointment.OverlapIdSet.Add(overlapId);
                                    appointment.RadioButtonVisibility = (nIndex == 0) ? Visibility.Visible : Visibility.Collapsed;
                                    nIndex++;
                                }
                            }
                            tempList = new List<FIFPAppointment>();
                            returnFlag = true;
                        }
                    }
                }
            }
            return returnFlag;
        }

        #region Overlap Checking algrithom


        //input  : sorted list of activitiesforplan for one unit        
        private bool FlagOverlappedPlans(List<PlanForSort> list)
        {
            bool returnFlag = false;
            int sumFlag = 0;
            List<FIFPAppointment> tempList = new List<FIFPAppointment>();

            foreach (PlanForSort a in list)
            {
                //sumflag == 0 means it is a new overlap group, so 
                //create a new list for activities in this overlap group
                //add the current activity
                //add the list to the result 
                if (sumFlag == 0)
                {
                    List<FIFPAppointment> l = new List<FIFPAppointment>();
                    l.Add(OriginalPlansDictionary[a.id]);

                    sumFlag += a.flag;

                    if (tempList.Count > 1)
                    {
                        foreach (FIFPAppointment p in tempList)
                        {
                            p.IsOverlapped = true;
                        }
                        returnFlag = true;
                    }
                    tempList = l;
                }
                //sumflag != 0 means it is in the process of the overlap group
                else
                {
                    if (a.flag == 1)
                    {
                        tempList.Add(OriginalPlansDictionary[a.id]);
                    }

                    sumFlag += a.flag;

                    if (sumFlag == 0)
                    {
                        if (tempList.Count > 1)
                        {
                            foreach (FIFPAppointment p in tempList)
                            {
                                p.IsOverlapped = true;
                            }
                            tempList = new List<FIFPAppointment>();
                            returnFlag = true;
                        }
                    }
                }
            }
            return returnFlag;
        }


        #endregion

        private void OverlapGrouping(List<PlanForSort> list)
        {
            int sumFlag = 0;
            List<FIFPAppointment> tempList = new List<FIFPAppointment>();

            foreach (PlanForSort plan in list)
            {
                //sumflag == 0 means it is a new overlap group, so 
                //create a new list for activities in this overlap group
                //add the current activity
                //add the list to the result 
                if (sumFlag == 0)
                {
                    List<FIFPAppointment> lstAppointment = new List<FIFPAppointment>();
                    lstAppointment.Add(OriginalPlansDictionary[plan.id]);

                    sumFlag += plan.flag;

                    if (tempList.Count > 1)//This is no needed. Later we have to modify.
                    {
                        overlapId++;
                        int nIndex = 0;
                        foreach (FIFPAppointment appointment in tempList)
                        {
                            appointment.Overlap_Id = overlapId;
                            appointment.RadioButtonVisibility = (nIndex == 0) ? Visibility.Visible : Visibility.Collapsed;
                            nIndex++;
                        }
                    }
                    tempList = lstAppointment;
                }
                //sumflag != 0 means it is in the process of the overlap group
                else
                {
                    if (plan.flag == 1)
                    {
                        tempList.Add(OriginalPlansDictionary[plan.id]);
                    }

                    sumFlag += plan.flag;

                    if (sumFlag == 0)
                    {
                        if (tempList.Count > 1)
                        {
                            overlapId++;
                            int nIndex = 0;
                            tempList = (from item in tempList
                                        orderby item.nIndex
                                        select item).ToList<FIFPAppointment>();
                            foreach (FIFPAppointment appointment in tempList)
                            {
                                appointment.Overlap_Id = overlapId;
                                appointment.RadioButtonVisibility = (nIndex == 0) ? Visibility.Visible : Visibility.Collapsed;
                                nIndex++;
                                //appointment.OverlapIdSet.Add(overlapId);
                            }
                            tempList = new List<FIFPAppointment>();
                        }
                    }
                }
            }
        }

        #endregion
        #endregion
    }
}
